package cn.wolfcode.luowowo.search.service.impl;

import cn.wolfcode.luowowo.search.domain.DestinationTemplate;
import cn.wolfcode.luowowo.search.domain.StrategyTemplate;
import cn.wolfcode.luowowo.search.query.StrategySearchQuery;
import cn.wolfcode.luowowo.search.repository.DestinationTemplateRepository;
import cn.wolfcode.luowowo.search.repository.StrategyTemplateRepository;
import cn.wolfcode.luowowo.search.service.IDestinationEsService;
import cn.wolfcode.luowowo.search.service.IStrategyEsService;
import cn.wolfcode.luowowo.search.vo.StatisVo;
import com.alibaba.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.InternalAggregation;
import org.elasticsearch.search.aggregations.InternalMultiBucketAggregation;
import org.elasticsearch.search.aggregations.bucket.composite.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import java.util.*;

@Service
public class StrategyEsServiceImpl implements IStrategyEsService {

    @Autowired
    private StrategyTemplateRepository repository;

    @Override
    public void save(StrategyTemplate template) {
        repository.save(template);
    }

    /**
     * 主题推荐
     * @return
     */
    @Override
    public List<Map<String, Object>> queryThemeCommend() {

        List<Map<String,Object>> data = new ArrayList<>();

        //步骤一：通过es 分组查询， 查询主题列表：themeid themeName count

        List<StatisVo> list = this.getStatsVOList("themeId", "themeName", "themeGroup");

        //优化2：取前面10个
        if(list.size()>10) list = list.subList(0,10);


        //步骤二：通过主题id：themeid 查询目的地的集合
        Map<String,Object> map = null;
        for (StatisVo vo : list) {
            map = new HashMap<>();
            // vo：主题
            map.put("theme",vo);
            //得到某一个主题下关联的目的地
            List<StatisVo> dests = this.getDestByThemeId(vo.getId());
            map.put("dests",dests);

            //将存储vo主题信息和目的地信息的map集合存储到list数据集合中
            data.add(map);
        }

        //步骤三：通过步骤一，步骤二的数据组装最终的data数据，并返回
        return data;

    }


    //通过主题id 查询目的地集合
    private List<StatisVo> getDestByThemeId(Long themeId) {
        List<StatisVo> vos = new ArrayList<>();
        List<StrategyTemplate> templates = repository.findByThemeId(themeId);
        //上面的查询查到的是 es攻略list集合 前端需要的只是目的地的id和name
        //优化3：目的地去除重复
        List<String> list = new ArrayList<>();
        for (StrategyTemplate template : templates) {
            if(!list.contains(template.getDestName())){
                StatisVo vo = new StatisVo();
                vo.setId(template.getId());
                vo.setName(template.getDestName());
                vos.add(vo);
                list.add(template.getDestName());
            }

        }
        return vos;
    }

    /**
     * 统计分组集合
     * @return
     */
    private List<StatisVo> getStatsVOList(String idField,String nameField,String groupName){

        //步骤一：通过es 分组查询， 查询主题列表：themeid themeName count

        //分组列对象集合
        List<CompositeValuesSourceBuilder<?>> sources = new ArrayList<>();
        TermsValuesSourceBuilder idSource = new TermsValuesSourceBuilder("id");
        idSource.field(idField);
        TermsValuesSourceBuilder nameSource = new TermsValuesSourceBuilder("name");
        nameSource.field(nameField);
        sources.add(idSource);
        sources.add(nameSource);

        //构建分组语法
        CompositeAggregationBuilder aggregationBuilder = new CompositeAggregationBuilder(groupName,sources);
        //es查询语句的构建类
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        builder.addAggregation(aggregationBuilder);
        //分页操作
        builder.withPageable(PageRequest.of(0,1));
        //明确指定查哪个索引，哪个类型
        builder.withIndices(StrategyTemplate.INDEX_NAME);
        builder.withTypes(StrategyTemplate.TYPE_NAME);

        //执行查询语句，返回结果
        AggregatedPage<StrategyTemplate> search = (AggregatedPage<StrategyTemplate>) repository.search(builder.build());

        //获取自定的分组名字中的所有数据  themeGroup
        InternalComposite themeGroup = (InternalComposite) search.getAggregation(groupName);
        //创建一个list集合准备存储bucket中的信息
        List<StatisVo> list = new ArrayList<>();

        for (CompositeAggregation.Bucket bucket : themeGroup.getBuckets()) {

            Long id = Long.parseLong(bucket.getKey().get("id").toString());
            String name = bucket.getKey().get("name").toString();
            long count = bucket.getDocCount();

            StatisVo vo = new StatisVo();
            vo.setId(id);
            vo.setName(name);
            vo.setCount(count);

            list.add(vo);
        }
        //优化1：根据目的地个数排序  ----list集合排序
        Collections.sort(list, new Comparator<StatisVo>() {
            //比较器，比较元素在集合中的位置
            //compare 比较方法，返回
            // <  0 : 表示小于
            // =  0 : 表示等于
            // >  0 : 表示大于
            @Override
            public int compare(StatisVo o1, StatisVo o2) {
                //倒序排
                Long ret = o2.getCount() - o1.getCount();
                return ret.intValue();
            }
        });
        return list;
    }

    /**
     * 查询攻略条件：国内，按省份分
     * @return
     */
    @Override
    public List<StatisVo> queryConditionChaina() {
        return this.getStatsVOList
                ("provinceId", "provinceName", "provinceGroup");
    }

    /**
     * 查询攻略条件：国外，按国家分
     * @return
     */
    @Override
    public List<StatisVo> queryConditionAbroads() {
        List<StatisVo> list = this.getStatsVOList
                ("countryId", "countryName", "countryGroup");
        //判断vo的name == 中国，剔除出来  集合数据删除使用迭代器方式删除
        Iterator<StatisVo> iterator = list.iterator();
        while (iterator.hasNext()){
            if("中国".equals(iterator.next().getName())){
                iterator.remove();
            }
        }
        return list;
    }

    /**
     * 查询攻略条件：主题，按主题分
     * @return
     */
    @Override
    public List<StatisVo> queryConditionThemes() {
        return this.getStatsVOList
                ("themeId", "themeName", "themeGroup");
    }


    @Override
    public Page query(StrategySearchQuery qo) {

        TermQueryBuilder query = null;
        PageRequest of = PageRequest.of(qo.getCurrentPage() - 1, qo.getPageSize(), Sort.Direction.DESC, qo.getOrderBy());

        if(qo.getType() == StrategySearchQuery.CONDITION_TYPE_COUNTRY){
            //国家
            query = QueryBuilders.termQuery("countryId",qo.getTypeValue());
        }else if(qo.getType() == StrategySearchQuery.CONDITION_TYPE_PROVINCE){
            //省份
            query = QueryBuilders.termQuery("provinceId",qo.getTypeValue());
        }else if(qo.getType() == StrategySearchQuery.CONDITION_TYPE_THEME){
            //主题
            query = QueryBuilders.termQuery("themeId",qo.getTypeValue());
        }

        if(query == null){
            return repository.findAll(of);
        }else{
            return repository.search(query,of);
        }
    }


    @Override
    public List<StrategyTemplate> findByDestName(String name) {
        return repository.findByDestName(name);
    }
}
